import sys
import datetime, time
import socket
from ctypes import *
from tdr import *
from tshmarket import *
from HandlerThread import HandlerThread
from threading import currentThread, Thread
import configparser


class GuangdaConnection(object):
    dict_msg = {}
    queue = []

    def __init__(self, parent=None):
        super(GuangdaConnection, self).__init__()
        self.queue.append(self)
        self.h = c_long(0)
        self.dll = windll.LoadLibrary("sipuicom64.dll")
        self.dict_msg = {}
        cf = configparser.ConfigParser()
        cf.read("config.ini")
        # 正式服务器用配置
        # self.ini_section = "server"
        # 测试服务器用配置
        self.ini_section = cf.get("default", "default_section")
        self.server_ip = cf.get(self.ini_section, "ip")
        self.server_port = int(cf.get(self.ini_section, "port"))
        self.username = cf.get(self.ini_section, "username")
        self.init_connection()

    def __del__(self):
        #  业务完成，退订
        ret = self.dll.TDR_UnsubscribeAll(self.h)
        if ret == 0:
            self.print_with_dt('ret=0, 退订行情成功！')
        else:
            self.print_with_dt('ret=%s，错误信息为：%s'%(ret,errorStringList[ret]))
        ret = self.dll.TDR_DisConnect(self.h)
        if ret == 0:
            self.print_with_dt('ret=0, 断开连接成功！')
        else:
            self.print_with_dt('ret=%s，错误信息为：%s'%(ret,errorStringList[ret]))
        ret = self.dll.TDR_Destroy(self.h)
        if ret == 0:
            self.print_with_dt('ret=0, 销毁句柄成功！')
        else:
            self.print_with_dt('ret=%s，错误信息为：%s'%(ret,errorStringList[ret]))

    def run(self):
        # time.sleep(0.1)
        while True:
            self.dict_msg["event_type"] = HEART_BEAT
            # log_file('生成心跳事件！%s' % self.dict_msg)
            return_msg = {}
            return_msg = HandlerThread.callback_heartbeat(self.dict_msg)
            if return_msg:
                self.subscribe_action(return_msg)
                log_file('收到订阅回调，调用self.subscribe_action处理订阅请求 %s' % return_msg)
                return_msg = {}
            # else:
            #     self.dict_msg = {}
                # log_file('回调心跳完成！self.dict_msg=%s' % self.dict_msg)
            time.sleep(0.2)

    def set_OnReceiveData(self, pUserParam, nDate, nMarketId, sCode, sName, uType, nServiceId, pData, nLen):
        # self.print_with_dt('set_OnReceiveData: 收到接口数据推送!')
        # self.print_with_dt(('pUserParam:%s, nDate:%s, nMarketId:%s,  sCode:%s, sName:%s, uType:%s, nServiceId:%s, '
        #     'pData:%s, nLen:%s' %(pUserParam, nDate, nMarketId, sCode, sName.decode('gb2312'), uType, nServiceId, pData, nLen)))
        log_file('set_OnReceiveData: 收到接口数据推送!')
        log_file(('pUserParam:%s, nDate:%s, nMarketId:%s,  sCode:%s, sName:%s, uType:%s, nServiceId:%s, '
            'pData:%s, nLen:%s' %(pUserParam, nDate, nMarketId, sCode, sName.decode('gb2312'), uType, nServiceId, pData, nLen)))
        data = PSH_StockMarketDataL2()
        data = PSH_StockMarketDataL2.from_address(pData)

        self.dict_msg = {}
        self.dict_msg["event_type"] = RECEIVE_SUCCES
        self.dict_msg["sCode"] = str(sCode, encoding='utf-8')
        self.dict_msg["sName"] = sName.decode('gb2312')
        for i in range(10):
            self.dict_msg["ask_price_%s" % i] = data.uAskPrice[i]
            self.dict_msg["ask_vol_%s" % i] = data.uAskVol[i]
            self.dict_msg["bid_price_%s" % i] = data.uBidPrice[i]
            self.dict_msg["bid_vol_%s" % i] = data.uBidVol[i]
        # self.dict_msg["nTime"] = data.nTime
        # self.dict_msg["nStatus"] = data.nStatus
        self.dict_msg["uPreClose"] = data.uPreClose
        # self.dict_msg["uOpen"] = data.uOpen
        # self.dict_msg["uHigh"] = data.uHigh
        # self.dict_msg["uLow"] = data.uLow
        # self.dict_msg["uMatch"] = data.uMatch
        # self.dict_msg["uNumTrades"] = data.uNumTrades
        # self.dict_msg["iVolume"] = data.iVolume
        # self.dict_msg["iTurnover"] = data.iTurnover
        # self.dict_msg["iTotalBidVol"] = data.iTotalBidVol
        # self.dict_msg["iTotalAskVol"] = data.iTotalAskVol
        # self.dict_msg["uWeightedAvgBidPrice"] = data.uWeightedAvgBidPrice
        # self.dict_msg["uWeightedAvgAskPrice"] = data.uWeightedAvgAskPrice
        # self.dict_msg["nIOPV"] = data.nIOPV
        # self.dict_msg["iTurnover"] = data.iTurnover
        # self.dict_msg["nYieldToMaturity"] = data.nYieldToMaturity
        # self.dict_msg["uHighLimited"] = data.uHighLimited
        # self.dict_msg["uLowLimited"] = data.uLowLimited
        # self.dict_msg["sPrefix"] = data.sPrefix
        #print('print(dict_msg) in set_OnReceiveData: %s' % self.dict_msg)
        # log_file('有回调事件！%s' % self.dict_msg)
        # 调用回调函数
        HandlerThread.callback_senddata(self.dict_msg)
        self.dict_msg = {}
        # log_file('完成回调！self.dict_msg=%s' % self.dict_msg)


    def set_OnErrorMsg(self, pUserParam, nError, nErrSource, uData):
        print('收到接口OnErrorMsg推送！')
        log_file('收到接口OnErrorMsg推送！')
        self.dict_msg = {}
        self.dict_msg["event_type"] = RECEIVE_ERROR
        self.dict_msg["nError"] = nError
        self.dict_msg["nErrSource"] = nErrSource
        self.dict_msg["uData"] = uData
        log_file('有回调事件！%s' % self.dict_msg)
        # 调用回调函数
        HandlerThread.callback_senddata(self.dict_msg)
        self.dict_msg = {}
        log_file('完成回调！self.dict_msg=%s' % self.dict_msg)

    def init_connection(self):
        # TDR_Create 建立句柄
        self.ONRECEIVEDATAFUNC = CFUNCTYPE(None, c_void_p, c_int, c_int, c_char_p, c_char_p, c_uint, c_int, c_void_p, c_int)
        self.ONERRORMSGFUNC = CFUNCTYPE(None, c_void_p, c_int, c_int, c_uint)
        self.callback_OnReceiveData = self.ONRECEIVEDATAFUNC(self.set_OnReceiveData)
        self.callback_OnErrorMsg = self.ONERRORMSGFUNC(self.set_OnErrorMsg)
        self.h = c_long(0)
        self.dll.TDR_Create.restype = c_long
        self.dll.TDR_Create.argtypes = [c_char_p, c_void_p, c_void_p, c_void_p, c_void_p, c_bool, c_bool]
        self.h = self.dll.TDR_Create(c_char_p(0), self.callback_OnReceiveData, c_void_p(0), self.callback_OnErrorMsg, c_void_p(0), c_bool(True), c_bool(True))
        # TDR_ConnectByDynamic 使用句柄连接服务器
        self.dll.TDR_ConnectByDynamic.restype = c_int
        self.dll.TDR_ConnectByDynamic.argtypes = [c_long, c_char_p, c_int, c_int, c_int, c_char_p, c_char_p, c_int, c_int]
        sIP = c_char_p(self.server_ip.encode('utf-8'))
        nPort = c_int(self.server_port)
        nIPType = c_int(SIP_SVR_WAN)
        nWanType = c_int(WAN_TC)
        sUserName = c_char_p(self.username.encode('utf-8'))
        sPassword = c_char_p("123456".encode('utf-8'))
        nLoginMode = c_int(UI_LOGIN_NORMAL)
        nTimeOutSec = c_int(15)
        ret = self.dll.TDR_ConnectByDynamic(self.h, sIP, nPort, nIPType, nWanType, sUserName, sPassword, nLoginMode, nTimeOutSec)
        if ret == 0:
            self.print_with_dt('ret=0, 登录成功！')
            log_file('ret=0, 登录成功！')
        else:
            self.print_with_dt('ret=%s，错误信息为：%s'%(ret,errorStringList[ret]))
            log_file('ret=%s，错误信息为：%s'%(ret,errorStringList[ret]))
        # time.sleep(5)
        # TDR_IsConnected
        # self.dll.TDR_IsConnected.restype = c_bool
        # self.dll.TDR_IsConnected.argtypes = [c_long]
        # ret = 0
        # ret = self.dll.TDR_IsConnected(self.h)
        # if ret == True:
        #     self.print_with_dt('TDR_IsConnected = True, 正在连接！')
        # else:
        #     self.print_with_dt('TDR_IsConnected = False，当前没有连接！')

        #  订阅行情
        self.dll.TDR_SubscribeByCode.restype = c_int
        self.dll.TDR_SubscribeByCode.argtypes = [c_long, c_char_p, c_char_p, c_ubyte, c_int]

        sMarket = c_char_p("SH".encode('utf-8'))
        sCode = c_char_p("510900".encode('utf-8'))
        ucMode = c_ubyte(RSS_MODE_NEW)
        nServiceId = c_int(ID_SH_MARKETDATA)
        ret = self.dll.TDR_SubscribeByCode(self.h, sMarket, sCode, ucMode, nServiceId)
        if ret == 0:
            # 退订之前的行情
            # 记录当前订阅成功的号
            # self.sCode = "510900"
            # self.str_market_now = "SH"
            log_file('成功订阅行情！%s' % "510900.SH")

        # self.run()

    def subscribe_action(self, input_dict_msg):
        if input_dict_msg:
            if input_dict_msg["user_input"]:
                user_input = input_dict_msg["user_input"]
                self.dll.TDR_UnsubscribeByCode.restype = c_int
                self.dll.TDR_UnsubscribeByCode.argtypes = [c_long, c_char_p, c_char_p, c_int]

                self.dll.TDR_UnsubscribeAll.restype = c_int
                self.dll.TDR_UnsubscribeAll.argtypes = [c_long]

                isSubscribed = False
                self.dict_msg = {}
                # SZ SH都用同一代码订阅一次
                _sMarket = c_char_p("SH".encode('utf-8'))
                _sCode = c_char_p(user_input.encode('utf-8'))
                _ucMode = c_ubyte(RSS_MODE_NEW)
                _nServiceId = c_int(ID_SH_MARKETDATA)
                ret = self.dll.TDR_SubscribeByCode(self.h, _sMarket, _sCode, _ucMode, _nServiceId)
                if ret == 0:
                    # 记录当前订阅成功的号
                    isSubscribed = True
                    self.dict_msg["sCode"] = user_input
                    self.dict_msg["sMarket"] = "SH"
                    log_file('订阅行情 %s.%s 成功！' % (user_input, "SH"))
                _sMarket = c_char_p("SZ".encode('utf-8'))
                _nServiceId = c_int(ID_SZ_MARKETDATA)
                ret = self.dll.TDR_SubscribeByCode(self.h, _sMarket, _sCode, _ucMode, _nServiceId)
                if ret == 0:
                    # 记录当前订阅成功的号
                    isSubscribed = True
                    self.dict_msg["sCode"] = user_input
                    self.dict_msg["sMarket"] = "SZ"
                    log_file('订阅行情 %s.%s 成功！' % (user_input, "SZ"))
                if isSubscribed:
                    log_file('成功订阅行情！%s' % user_input)
                    self.dict_msg["event_type"] = SUBSCRIBE_SUCCESS
                else:
                    self.dict_msg["event_type"] = SUBSCRIBE_FAIL
                    self.dict_msg["sCode"] = user_input
                # 回调订阅结果
                HandlerThread.callback_senddata(self.dict_msg)
                self.dict_msg = {}
                isSubscribed = False
                #     log_file('订阅行情已成功，开始尝试退订行情')
                #     self.dict_msg["event_type"] = SUBSCRIBE_SUCCESS
                #     # 退订之前的行情
                #     _sMarket = c_char_p(input_dict_msg["sMarket"].encode('utf-8'))
                #     _sCode = c_char_p(input_dict_msg["sCode"].encode('utf-8'))
                #     _nServiceId = c_int(ID_SH_MARKETDATA)
                #     ret2 = self.dll.TDR_UnsubscribeByCode(self.h, _sMarket, _sCode, _nServiceId)
                #     if ret2 ==0:
                #         log_file('退订行情 %s.%s 成功！' % (input_dict_msg["sCode"], input_dict_msg["sMarket"]))
                #     else:
                #         log_file('退订行情 %s.%s 失败！，错误信息是%s。' % (
                #             input_dict_msg["sCode"], input_dict_msg["sMarket"], errorStringList[ret]))
                # else:
                #     self.dict_msg["event_type"] = SUBSCRIBE_FAIL
                #     self.dict_msg["sCode"] = user_input
                # self.event = True

    def print_with_dt(self, print_str):
        now = datetime.datetime.now()
        dt = now.strftime("%Y-%m-%d %H:%M:%S")
        print('%s %s' % (dt, print_str))
        #log_file('%s %s' % (dt, print_str))


    def print_ret(self, ret):
        if ret == 0:
            log_file('操作成功！')
        else:
            log_file("操作失败，失败原因: %d %s" % (ret, errorStringList[ret]))

def log_file(log_str):
    str_dt = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    str_dt2 = datetime.datetime.now().strftime("%Y-%m-%d")
    log_filename = '%s_server.log' % str_dt2
    with open(log_filename, 'a', encoding='utf-8') as my_logfile:
        log_str = '%s %s' %(str_dt, log_str)
        my_logfile.write(log_str + '\n')


if __name__ == '__main__':
    data_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    data_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    DATA_ADDR = ('0.0.0.0', 9999)
    data_socket.bind(DATA_ADDR)
    data_socket.listen(99)
    print('在 %s:%s 开始等待连接...' % DATA_ADDR)
    log_file('在 %s:%s 开始等待连接...' % DATA_ADDR)

    market_connection = GuangdaConnection()
    main_thread = Thread(target=market_connection.run)
    main_thread.setDaemon(True)
    main_thread.start()

    while True:
        print('主循环开始，等待连接...')
        try:
            sock, addr = data_socket.accept()
            # print('Received new client connection. %s:%s' % (addr[0], addr[1]))
        except KeyboardInterrupt:
            exit('\nByeBye!')
        print('Received new client connection. %s:%s' % (addr[0], addr[1]))
        log_file('Received new client connection. %s:%s' % (addr[0], addr[1]))
        th = HandlerThread(sock)
        t = Thread(target=th.handler)
        t.setDaemon(True)
        t.start()

    s.close()
